﻿using System.Security.Permissions;
using System.Windows.Forms;
using Microsoft.SharePoint.Administration;
using System.Data;
using System;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Drawing.Imaging;
using MicroLink.SharePointServices.SolutionAdministration;
using MicroLink.SharePointServices.WebApplications;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio;

namespace MicroLink.StsDev2008AddIn
{
    /// <summary>
    /// Summary description for MyControl.
    /// </summary>
    public partial class MyControl : UserControl
    {
        private const string SolutionNameColumn = "SolutionName";
        private const string DeploymentStateColumn = "DeploymentState";
        private const string DeployedToColumn = "DeployedTo";
        private const string SolutionIdColumn = "SolutionId";

        public MyControl()
        {
            InitializeComponent();

            m_dataGridView.Columns[SolutionNameColumn].DataPropertyName = "SolutionName";
            m_dataGridView.Columns[DeploymentStateColumn].DataPropertyName = "DeploymentState";
            m_dataGridView.Columns[DeployedToColumn].DataPropertyName = "DeployedTo";
            m_dataGridView.Columns[SolutionIdColumn].DataPropertyName = "SolutionId";

            m_dataGridView.DataSource = new SolutionDataTable();
        }

        protected override void OnCreateControl()
        {
            base.OnCreateControl();
            m_dataGridView.DataSource = new SolutionDataTable();
        }

        /// <summary> 
        /// Let this control process the mnemonics.
        /// </summary>
        [UIPermission(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
        protected override bool ProcessDialogChar(char charCode)
        {
            // If we're the top-level form or control, we need to do the mnemonic handling
            if (charCode != ' ' && ProcessMnemonic(charCode))
            {
                return true;
            }
            return base.ProcessDialogChar(charCode);
        }

        /// <summary>
        /// Enable the IME status handling for this control.
        /// </summary>
        protected override bool CanEnableIme
        {
            get
            {
                return true;
            }
        }

        private void AddMenuItems(object sender, EventArgs e)
        {
            Guid solutionGuid = GetSelectedSolutionGuid();

            SolutionProperties solution = SolutionManager.GetSolution(solutionGuid);

            ToolStripDropDownItem solutionMenu = sender as ToolStripDropDownItem;

            if (solutionMenu != null)
            {
                solutionMenu.DropDownItems.Clear();

                ToolStripMenuItem addItem = new ToolStripMenuItem("Add", AddImage);
                addItem.Click += new EventHandler(AddSolution);
                solutionMenu.DropDownItems.Add(addItem);

                if (solution != null)
                {
                    if (solution.Deployed)
                    {
                        if (solution.ContainsWebApplicationResource)
                        {
                            ToolStripMenuItem retractMenu = CreateRetractFromMenu(solution);
                            solutionMenu.DropDownItems.Add(retractMenu);

                            ToolStripMenuItem deployMenu = CreateDeployToMenu(solution);
                            solutionMenu.DropDownItems.Add(deployMenu);
                        }
                        else
                        {
                            ToolStripMenuItem retractItem = new ToolStripMenuItem("Retract", RetractImage);
                            retractItem.Click += new EventHandler(RetractSolution);
                            solutionMenu.DropDownItems.Add(retractItem);
                        }
                    }
                    else
                    {
                        if (solution.ContainsWebApplicationResource)
                        {
                            ToolStripMenuItem deployMenu = CreateDeployToMenu(solution);
                            solutionMenu.DropDownItems.Add(deployMenu);
                        }
                        else
                        {
                            ToolStripMenuItem deployMenu = new ToolStripMenuItem("Deploy");
                            deployMenu.Click += new EventHandler(DeploySolution);
                            solutionMenu.DropDownItems.Add(deployMenu);
                        }

                        ToolStripMenuItem deleteItem = new ToolStripMenuItem("Delete", DeleteImage);
                        deleteItem.Click += new EventHandler(DeleteSolution);
                        solutionMenu.DropDownItems.Add(deleteItem);
                    }
                }

                ToolStripMenuItem refreshItems = new ToolStripMenuItem("Refresh", RefreshImage);
                refreshItems.Click += new EventHandler(RefreshSolutions);
                solutionMenu.DropDownItems.Add(refreshItems);
            }
        }

        #region AddSolution
        void AddSolution(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                WriteOutput(string.Format(
                        "Adding Solution: {0}\r\n",
                        openFileDialog.FileName));
                try
                {
                    SPSolution solution = SPFarm.Local.Solutions.Add(openFileDialog.FileName);
                    WriteOutput(string.Format("Solution {0}-{1} Added.\r\n", solution.Name, solution.Id.ToString()));
                }
                catch (Exception ex)
                {
                    WriteOutput(string.Format("Solution Add failed: {0}\r\n", ex.Message));
                }

                m_dataGridView.DataSource = new SolutionDataTable();
            }
        }
        #endregion

        #region RefreshSolutions
        void RefreshSolutions(object sender, EventArgs e)
        {
            m_dataGridView.DataSource = new SolutionDataTable();
        }
        #endregion

        #region RetractFromHandler
        void RetractFromHandler(object sender, EventArgs e)
        {
            Guid solutionGuid = GetSelectedSolutionGuid();

            ToolStripMenuItem theSender = sender as ToolStripMenuItem;

            Collection<string> collection;

            WriteOutput(string.Format("Retract Solution {0} from {1}\r\n", solutionGuid, theSender.Text));

            if (theSender.Text == "All")
                collection = SolutionManager.GetSolution(solutionGuid).DeployedWebApplications;
            else
            {
                collection = new Collection<string>();
                collection.Add(theSender.Text);
            }

            SolutionManager.RetractSolution(solutionGuid, collection);
        }
        #endregion

        #region DeployToHandler
        void DeployToHandler(object sender, EventArgs e)
        {
            Guid solutionGuid = GetSelectedSolutionGuid();

            ToolStripMenuItem theSender = sender as ToolStripMenuItem;

            Collection<string> collection;

            WriteOutput(string.Format("Deploy Solution {0} to {1}\r\n", solutionGuid, theSender.Text));

            if (theSender.Text == "All")
                collection = WebApplicationManager.WebApplications;
            else
            {
                collection = new Collection<string>();
                collection.Add(theSender.Text);
            }

            SolutionManager.DeploySolution(solutionGuid, collection);
        }
        #endregion

        #region DeleteSolution
        void DeleteSolution(object sender, EventArgs e)
        {
            Guid solutionGuid = GetSelectedSolutionGuid();
            WriteOutput(string.Format("Delete Solution {0}\r\n", solutionGuid));
            try
            {
                SolutionManager.DeleteSolution(solutionGuid);
                m_dataGridView.DataSource = new SolutionDataTable();
            }
            catch (Exception ex)
            {
                WriteOutput(string.Format("Error Deleting Solution: {0}\r\n", ex.Message));
            }
        }
        #endregion

        #region DeploySolution
        void DeploySolution(object sender, EventArgs e)
        {
            Guid solutionGuid = GetSelectedSolutionGuid();
            WriteOutput(string.Format("Deploy Solution {0} Globally\r\n", solutionGuid));
            try
            {
                SolutionManager.DeploySolution(solutionGuid);
                m_dataGridView.DataSource = new SolutionDataTable();
            }
            catch (Exception ex)
            {
                WriteOutput(string.Format("Error Deploying Solution: {0}\r\n", ex.Message));
            }
        }
        #endregion

        #region RetractSolution
        void RetractSolution(object sender, EventArgs e)
        {
            Guid solutionGuid = GetSelectedSolutionGuid();
            WriteOutput(string.Format("Retract Global Solution {0}\r\n", solutionGuid));
            try
            {
                SolutionManager.RetractSolution(solutionGuid);
                m_dataGridView.DataSource = new SolutionDataTable();
            }
            catch (Exception ex)
            {
                WriteOutput(string.Format("Error Retracting Solution: {0}\r\n", ex.Message));
            }
        }
        #endregion

        #region CreateDeployToMenu
        private ToolStripMenuItem CreateDeployToMenu(SolutionProperties solution)
        {
            ToolStripMenuItem deployMenu = new ToolStripMenuItem("Deploy To");
            foreach (string spWebApp in WebApplicationManager.WebApplications)
            {
                if (!solution.DeployedWebApplications.Contains(spWebApp))
                {
                    ToolStripMenuItem deployTo = new ToolStripMenuItem(spWebApp);
                    deployTo.Click += new EventHandler(DeployToHandler);
                    deployMenu.DropDownItems.Add(deployTo);
                }
            }

            return deployMenu;
        }
        #endregion

        #region CreateRetractFromMenu
        private ToolStripMenuItem CreateRetractFromMenu(SolutionProperties solution)
        {
            ToolStripMenuItem retractMenu = new ToolStripMenuItem("Retract From", RetractImage);

            foreach (string spWebApp in solution.DeployedWebApplications)
            {
                ToolStripMenuItem retractFrom = new ToolStripMenuItem(spWebApp, RetractImage);
                retractFrom.Click += new EventHandler(RetractFromHandler);
                retractMenu.DropDownItems.Add(retractFrom);
            }

            return retractMenu;
        }
        #endregion

        #region GetSelectedSolutionGuid
        private Guid GetSelectedSolutionGuid()
        {
            string solutionGuidString = m_dataGridView.CurrentRow.Cells[SolutionIdColumn].Value as string;
            Guid solutionGuid = new Guid(solutionGuidString);

            return solutionGuid;
        }
        #endregion

        #region RetractImage
        Bitmap m_retractImage;
        private Bitmap RetractImage
        {
            get
            {
                if (m_retractImage == null)
                    m_retractImage = GetImage(Resources.Revert, 100, 27, 16, 16);

                return m_retractImage;
            }
        }
        #endregion

        #region RefreshImage
        private Bitmap m_refreshImage;
        private Bitmap RefreshImage
        {
            get
            {
                if (m_refreshImage == null)
                    m_refreshImage = GetImage(Resources.Refresh, 32, 7, 16, 16);

                return m_refreshImage;
            }
        }
        #endregion

        #region AddImage
        Bitmap m_addImage;
        private Bitmap AddImage
        {
            get
            {
                if (m_addImage == null)
                {
                    m_addImage = GetImage(Resources.Add, 0, 0, 16, 16);
                    Color c = m_addImage.GetPixel(0, 0);
                    m_addImage.MakeTransparent(c);
                }
                return m_addImage;
            }
        }
        #endregion

        #region DeleteImage
        Bitmap m_deleteImage;
        private Bitmap DeleteImage
        {
            get
            {
                if (m_deleteImage == null)
                    m_deleteImage = GetImage(Resources.Remove, 40, 16, 16, 16);

                return m_deleteImage;
            }
        }
        #endregion

        #region GetImage
        private Bitmap GetImage(Bitmap originalImage, int xOffSet, int yOffSet, int width, int height)
        {
            Bitmap croppedImage = new Bitmap(width, height);
            using (Graphics graphic = Graphics.FromImage(croppedImage))
            {
                graphic.DrawImage(originalImage, new Rectangle(0, 0, width, height), new Rectangle(xOffSet, yOffSet, width, height), GraphicsUnit.Pixel);
            }

            return croppedImage;
        }
        #endregion

        #region OutputWindow
        private IVsOutputWindowPane m_pane;
        private IVsOutputWindowPane OutputWindow
        {
            get
            {
                if (m_pane == null)
                {
                    var outputWindow = GetService(
                    typeof(SVsOutputWindow)) as IVsOutputWindow;
                    IVsOutputWindowPane pane;
                    Guid guidGeneralPane = VSConstants.GUID_OutWindowGeneralPane;
                    outputWindow.GetPane(ref guidGeneralPane, out pane);
                }

                return m_pane;
            }
        }
        #endregion

        #region WriteOutput
        private void WriteOutput(string outputText)
        {
            if (OutputWindow != null)
            {
                OutputWindow.OutputString(outputText);
            }
            else
            {
                System.Console.WriteLine(outputText);
            }
        }
        #endregion
    }
}
